#include "head.h"

extern struct attack_stats attack;
extern int SNIFFER_MODE;
extern int packetfd;
extern struct trafflog log;

extern char old_log_buff[];    
extern int  old_log_buff_count;

struct status
{
	struct	status *next;
	__u16 	saddr;
	__u16	daddr;
	unsigned long	count;
	char	*start_time;
	char	*end_time;
};

struct openport
{
	struct openport *next;
	__u16 port;	
} ;

struct openport *portlist_head;
struct openport *portlist_tail;

void process_tcp(const struct sbuff *sbuffptr) 
{
	struct tcphdr *tcph=sbuffptr->h.tcph;
	struct iphdr *iph=sbuffptr->nh.iph;
   

	if( SNIFFER_MODE)
		print_tcph(tcph);
	if(tcph->syn&&!tcph->ack) {
		attack.synflood++;
	if(!attack.synflood)
		memcpy(&attack.synsbuff,sbuffptr,sizeof(struct sbuff));
   }	

   check_scan_tcp(sbuffptr);
   check_dos_land(sbuffptr);
   check_dos_winnuke(sbuffptr);
   check_dos_longurl(sbuffptr);
   check_probe_cgi(sbuffptr);

}


void process_udp(const struct sbuff *sbuffptr)
{
   struct udphdr *udph=sbuffptr->h.udph;

   if( SNIFFER_MODE)
   	print_udph(udph);
 }

void process_icmp(const struct sbuff *sbuffptr)
{
   struct icmphdr *icmph=sbuffptr->h.icmph;
   if(SNIFFER_MODE)
   	print_icmph(icmph);
}


void process_igmp(const struct sbuff *sbuffptr)
{
}


void check_dos_land(const struct sbuff *sbuffptr)
{

   struct iphdr *iph=sbuffptr->nh.iph;
   struct tcphdr *tcph=sbuffptr->h.tcph;

   if(!tcph->syn)     
	return;
   if(iph->saddr!=iph->daddr || tcph->source!=tcph->dest)
        return;
   do_log("land",sbuffptr);

}

void check_dos_winnuke(const struct sbuff *sbuffptr)
{
   struct tcphdr *tcph=sbuffptr->h.tcph;

   if(ntohs(tcph->dest)==139&&tcph->urg)
	do_log("winnuke",sbuffptr);
}

void check_dos_longurl(const struct sbuff *sbuffptr)
{
   struct tcphdr *tcph=sbuffptr->h.tcph;
   char *data=sbuffptr->data;

   if(ntohs(tcph->dest)!=80 || !tcph->ack)
	return;

   if(strlen(data)>=MAX_URL_LEN){
	do_log("Too_long_url",sbuffptr);
	printf("%s",data);
   }
}

void check_probe_cgi(const struct sbuff *sbuffptr)
{
   
   struct tcphdr *tcph=sbuffptr->h.tcph;
   char *data=sbuffptr->data;

   if(ntohs(tcph->dest)!=80||!tcph->ack||!tcph->psh)
	return;   
  
   if((char *)strcasestr(data,"showcode.asp")!=NULL)
   	do_log("showcode",sbuffptr);
   if((char *)strcasestr(data,"phf?")!=NULL)
   	do_log("phf",sbuffptr);
   if((char *)strcasestr(data,"/glimpse")!=NULL)
	do_log("glimpse_cgi",sbuffptr);
   if((char *)strcasestr(data,"/htmlscript")!=NULL)
	do_log("htmlscript",sbuffptr);
   if((char *)strcasestr(data,"/bin/sh")!=NULL)
	do_log("/bin/sh",sbuffptr);
   if((char *)strcasestr(data,"test")!=NULL)
	do_log("test",sbuffptr);
   if((char *)strcasestr(data,"asp..")!=NULL)
	do_log("asp..",sbuffptr);
}

void check_scan_tcp(const struct sbuff *sbuffptr)
{
   struct tcphdr *tcph=sbuffptr->h.tcph;
   char alter[100];

   if(tcph->syn&&!tcph->ack&&!findport(ntohs(tcph->dest))){
	snprintf(alter,sizeof(alter),"SYN_to_unopen_port%d",ntohs(tcph->dest));
	do_log(alter,sbuffptr);
   }
   if(tcph->res2)
	do_log("queso",sbuffptr);
   if(tcph->fin&&tcph->syn&&!tcph->rst&&!tcph->psh&&!tcph->ack&&!tcph->urg)
      	do_log("SF_scan",sbuffptr);
   if(!tcph->fin&&!tcph->syn&&!tcph->rst&&!tcph->psh&&!tcph->ack&&!tcph->urg)
      	do_log("NULL_scan",sbuffptr);
   if(tcph->fin&&tcph->syn&&tcph->rst&&tcph->psh&&tcph->ack&&tcph->urg)
      	do_log("FULL_Xmas_scan",sbuffptr);
   if(tcph->fin&&!tcph->syn&&!tcph->rst&&tcph->psh&&!tcph->ack&&tcph->urg)
      	do_log("XMAS_Scan(FPU)",sbuffptr);
     
}

void check_dos_pingofdeath(const struct sbuff *sbuffptr)
{

   struct iphdr *iph=sbuffptr->nh.iph;

   if(iph->protocol!=1) return;
   do_log("Ping_of_death",sbuffptr);

}

void stats()
{
   struct sbuff *sbuffptr;

   if(attack.synflood>MAX_SYN){
   	sbuffptr=&attack.synsbuff;  
	do_log("synflood",sbuffptr);
   }	
 
   bzero(&attack,sizeof(attack));
   alarm(1);
}

void print_iph(const struct iphdr *iph)
{  	 
   printf("ip ver=%d\n",iph->version);
   printf("ip ihl=%d bytes\n",iph->ihl<<2);
   printf("ip tos=%d\n",iph->tos);
   printf("ip tot_len=%d\n",ntohs(iph->tot_len));
   printf("ip id=%d",ntohs(iph->id));
   printf(" %c ",(iph->frag_off&htons(IP_MF))?'M':'-');
   printf("ip frag_off=ox%x",ntohs(iph->frag_off&htons(IP_OFFSET)));
   printf("ip ttl=%d",iph->ttl);
   printf("ip protocol=%d\n",iph->protocol);
   printf("From %s  ",inet_ntoa(iph->saddr));
   printf("To %s\n",inet_ntoa(iph->daddr));
}

void print_tcph(const struct tcphdr *tcph)
{
   printf("tcp sourse=%d\n",ntohs(tcph->source));
   printf("tcp dest=%d\n",ntohs(tcph->dest));
   printf("%c",tcph->fin==1?'F':'*');
   printf("%c",tcph->syn==1?'S':'*');
   printf("%c",tcph->rst==1?'R':'*');
   printf("%c",tcph->psh==1?'P':'*');
   printf("%c",tcph->ack==1?'A':'*');
   printf("%c",tcph->urg==1?'U':'*');
   printf(" Tcp seq=%ld\n",ntohl(tcph->seq));
   printf(" Tcp ack_seq=%d\n",ntohl(tcph->ack_seq)); 
   printf("window=%d\n",ntohs(tcph->window));
}

void print_udph(const struct udphdr *udph)
{
   printf("udp sourse=%d\n",ntohs(udph->source));
   printf("udp dest=%d\n",ntohs(udph->dest)); 
}

void print_icmph(const struct icmphdr *icmph)
{
}

void err_quit(char * errbuff)
{
   printf(errbuff);
   exit(-2);
} 

static char * fillspace(char * string)  /*used in do_log()*/
{
   int i;
   for(i=0;string[i];i++){
      if(string[i]==' ')   string[i]='_';
   }   
   return string;
}

void do_log(char *msg,const struct sbuff *sb)
{
    time_t	  ticks;
	char      sendbuff[MAXBUFFSIZE];
	struct    iphdr  *iph=sb->nh.iph;
		
	printf("old_log_buff=%s\n",old_log_buff);
	
	if(!strcmp(old_log_buff,msg)){ 
		old_log_buff_count++;
		printf("old_log_buff_count=%d\n",old_log_buff_count);
		return;
	}
	if(old_log_buff_count) {
		ticks=time(NULL);
        bzero(sendbuff,sizeof(sendbuff));
	
        snprintf(sendbuff,sizeof(sendbuff),
                 "%s %s %s %d %s",
                 inet_ntoa(iph->saddr),
				 inet_ntoa(iph->daddr),
		 "the last message repeated",
		 old_log_buff_count,
                 fillspace((char *)ctime(&ticks))
                 );
if(fputs(sendbuff,logfd)==EOF)   
    err_quit("fputs");
        }

	old_log_buff_count=0;
	if(strncpy(old_log_buff,msg,MAXBUFFSIZE)==NULL){
        	printf("strncpy error\n");
	}
        printf("old_log_buff now:%s\n",old_log_buff);
	ticks=time(NULL);
        bzero(sendbuff,sizeof(sendbuff));
	        
        snprintf(sendbuff,sizeof(sendbuff),
                 "%s %s %s %s",
		 
                 inet_ntoa(iph->saddr),
                 inet_ntoa(iph->daddr),
		 msg,
   
                 fillspace((char *)ctime(&ticks))
                 );
if(fputs(sendbuff,logfd)==EOF)   
    err_quit("fputs");
	return;

}


void  final_quit()
{
   struct ifreq ifr;
   strcpy(ifr.ifr_name,"eth0");
   if(ioctl(packetfd,SIOCGIFFLAGS,&ifr)<0)
      err_quit("ioctl1");
   ifr.ifr_flags&=~IFF_PROMISC;
   if(ioctl(packetfd,SIOCSIFFLAGS,&ifr)<0)
      err_quit("Can not exit PROMISC mode\n");
   printf("\n%ld IP packet received\n",log.ippacket);
   printf("%ld Bad IP packet\n",log.bad_ippacket);
   printf("%ld TCP packets\n",log.tcppacket);
   printf("%ld UDP packets\n",log.udppacket);
   printf("%ld ICMP packets\n",log.icmppacket);
   printf("%ld IGMP packets\n",log.igmppacket);
   printf("%ld Unknow packets\n",log.unknownpacket);
   printf("%ld Fragment\n",log.fragment);
   printf("%ld Total bytes\n",log.totalbytes);   
   printf("Bye!\n");
   exit(0);
    
}


int findport(__u16 port)
{
   int i=0;
   struct openport *temp;
   
   if(portlist_head->port==1){
   	i=1;
	return i;
   }

   for(temp=portlist_head->next;temp;temp=temp->next)
      	if(port==temp->port) {
		i=1;
		break;
	}
   
   return i;
       
}

static void add_port_to_list(__u16 port)
{
   struct openport *temp=malloc(sizeof(struct openport));
   temp->port=port;
   temp->next=NULL;
   portlist_tail->next=temp;
   portlist_tail=temp;
}

void process_cfg()
{

   FILE *fp;
   char i[100];
   int  t;
   __u16 dport;

   portlist_head=malloc(sizeof(struct openport));
   portlist_tail=portlist_head;
   portlist_head->port=0;
   portlist_head->next=NULL;

   fp=fopen("./openport.conf","r");
   if(!fp){
	printf("openport.conf is not exist:all port is defined open.\n");
	portlist_head->port=1;
	return;	
   }

   for(t=0;t<3000;t++){
      bzero(i,sizeof(i));
      if(fgets(i,sizeof(i),fp)==NULL) break;
      
      if(i[0]=='#'||i[0]=='\n'||!isdigit(i[0]))  continue;
      dport=(__u16)atoi(i); 
      if(dport){
		add_port_to_list(dport);
        printf("Add port %d to openport list\n",dport);
      }	
   } 
}